#include <iostream>
#include <vector>
#include <string>
#include <unordered_map>
#include <chrono>
#include <thread>
#include <set>
#include <sw/redis++/redis++.h>

using namespace std;
using namespace sw::redis;

// sadd and smembers
void Test1(Redis& redis)
{
    redis.flushall();
    cout << "sadd and smembers" << endl;

    // 一次添加一个元素
    redis.sadd("key", "1");

    // 一次添加多个元素
    redis.sadd("key", {"2", "3", "4"});
    vector<string> values = {"5", "6", "7"};
    redis.sadd("key", values.begin(), values.end());

    // 此处使用 set 来保存 smembers 的结果更合适
    set<string> ret;
    // inserter 的第二个参数可以是 ret 中的任意一个迭代器，因为 set 是有插入规则的
    auto it = inserter(ret, ret.end());
    redis.smembers("key", it);
    for(auto& e : ret) cout << e << " ";
    cout << endl;
}

// sismember and scard
void Test2(Redis& redis)
{
    redis.flushall();
    cout << "sismember and scard" << endl;
    
    redis.sadd("key", {"1", "2", "3"});

    bool ret = redis.sismember("key", "1");
    cout << ret << endl;

    long long len = redis.scard("key");
    cout << "len: " << len << endl; 
} 

// spop
void Test3(Redis& redis)
{
    redis.flushall();
    cout << "spop" << endl;
    
    redis.sadd("key", {"1", "2", "3"});
    auto ret = redis.spop("key");
    if(ret)
        cout << ret.value() << endl;
    else
        cout << "set is empty" << endl;
}

// sinter and sinterstore
void Test4(Redis& redis)
{
    redis.flushall();
    cout << "sinter and sinterstore" << endl;

    redis.sadd("key1", {"111", "222", "333"});
    redis.sadd("key2", {"111", "222", "444"});

    set<string> ret;
    auto it = inserter(ret, ret.begin());
    redis.sinter({"key1", "key2"}, it);
    for(auto& e : ret) cout << e << " ";
    cout << endl;

    redis.sinterstore("key3", {"key1", "key2"});
    ret.clear();
    it = inserter(ret, ret.begin());
    redis.smembers("key3", it);
    for(auto& e : ret) cout << e << " ";
    cout << endl;
}

// sunion and sunionstore
void Test5(Redis& redis)
{
    redis.flushall();
    cout << "sunion and sunionstore" << endl;

    redis.sadd("key1", {"111", "222", "333"});
    redis.sadd("key2", {"111", "222", "444"});

    set<string> ret;
    auto it = inserter(ret, ret.begin());
    redis.sunion({"key1", "key2"}, it);
    for(auto& e : ret) cout << e << " ";
    cout << endl;

    redis.sunionstore("key3", {"key1", "key2"});
    ret.clear();
    it = inserter(ret, ret.begin());
    redis.smembers("key3", it);
    for(auto& e : ret) cout << e << " ";
    cout << endl;
}

int main()
{
    sw::redis::Redis redis("tcp://127.0.0.1:6379");
    // Test1(redis);
    // Test2(redis);
    // Test3(redis);
    // Test4(redis);
    Test5(redis);

    return 0;
}